using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using Microsoft.VisualStudio.TextTemplating;
using PrismFactory.SoftwareFactory.Properties;

namespace PrismFactory.SoftwareFactory.Actions.Temp
{
    public class TemplateHost : MarshalByRefObject, ITextTemplatingEngineHost
    {
        // Fields
        private readonly IDictionary<string, PropertyData> arguments;
        private readonly string binPath;
        private CompilerErrorCollection errors;
        private const string propertyDirectiveProcessorName = "PropertyProcessor";

        // Methods
        public TemplateHost(string binPath, IDictionary<string, PropertyData> arguments)
        {
            if (binPath == null)
            {
                throw new ArgumentNullException("binPath");
            }
            if (arguments == null)
            {
                throw new ArgumentNullException("arguments");
            }
            this.binPath = new DirectoryInfo(binPath).FullName;
            this.arguments = arguments;
            CurrentHost = this;
        }

        public object GetHostOption(string optionName)
        {
            //throw new Exception("The method or operation is not implemented.");
            return null;
        }

        public bool LoadIncludeText(string requestFileName, out string content, out string location)
        {
            if (requestFileName == null)
            {
                throw new ArgumentNullException("filePath");
            }
            location = ResolveFileName(requestFileName);
            if (!location.StartsWith(binPath))
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, "TemplateHost_IncludeTemplateNotInPackage", new object[] {location, binPath}));
            }
            content = File.ReadAllText(location);
            return true;
        }

        public void LogErrors(CompilerErrorCollection errors)
        {
            this.errors = errors;
        }

        public AppDomain ProvideTemplatingAppDomain(string content)
        {
            return AppDomain.CurrentDomain;
        }

        public string ResolveAssemblyReference(string assemblyReference)
        {
            string path = Path.Combine(binPath, assemblyReference);
            if (File.Exists(path))
            {
                return path;
            }
            if (!File.Exists(assemblyReference))
            {
                path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "PublicAssemblies"), assemblyReference);
                if (File.Exists(path))
                {
                    return path;
                }
                path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "PrivateAssemblies"), assemblyReference);
                if (File.Exists(path))
                {
                    return path;
                }
                if (string.IsNullOrEmpty(AppDomain.CurrentDomain.SetupInformation.PrivateBinPath))
                {
                    return assemblyReference;
                }
                foreach (string str2 in AppDomain.CurrentDomain.SetupInformation.PrivateBinPath.Split(new[] {';'}, StringSplitOptions.RemoveEmptyEntries))
                {
                    path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, str2), assemblyReference);
                    if (File.Exists(path))
                    {
                        return path;
                    }
                }
            }
            return assemblyReference;
        }

        public Type ResolveDirectiveProcessor(string processorName)
        {
            if (processorName == null)
            {
                throw new ArgumentNullException("processorName");
            }
            if (string.Compare(processorName, "PropertyProcessor", StringComparison.OrdinalIgnoreCase) == 0)
            {
                return typeof (PropertiesDirectiveProcessor);
            }
            return null;
        }

        public string ResolveFileName(string fileName)
        {
            if (!Path.IsPathRooted(fileName))
            {
                return Path.Combine(binPath, fileName);
            }
            return fileName;
        }

        public string ResolveParameterValue(string directiveId, string processorName, string parameterName)
        {
            throw new NotImplementedException("The method or operation is not implemented.");
        }

        public string ResolvePath(string path)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public void SetFileExtension(string extension)
        {
        }

        public void SetOutputEncoding(Encoding encoding, bool fromOutputDirective)
        {
            throw new NotImplementedException("The method or operation is not implemented.");
        }

        // Properties
        public IDictionary<string, PropertyData> Arguments
        {
            get { return arguments; }
        }

        public static TemplateHost CurrentHost { get; set; }

        public CompilerErrorCollection Errors
        {
            get { return errors; }
        }

        public IList<string> StandardAssemblyReferences
        {
            get { return null; }
        }

        public IList<string> StandardImports
        {
            get { return null; }
        }

        public string TemplateFile { get; set; }
    }
}